package com.solution.wx.core.service.impl;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.solution.admin.settings.entity.KeyMapEntity;
import com.solution.admin.settings.service.KeyMapService;
import com.solution.admin.sysconfig.entity.WechatArticleEntity;
import com.solution.admin.sysconfig.entity.WechatMsgConfigEntity;
import com.solution.admin.sysconfig.entity.WechatMsgDefaultReplyEntity;
import com.solution.admin.sysconfig.entity.WechatMsgEventReplyEntity;
import com.solution.admin.sysconfig.entity.WechatMsgKeywordReplyEntity;
import com.solution.admin.sysconfig.service.WechatArticleService;
import com.solution.admin.sysconfig.service.WechatMsgConfigService;
import com.solution.admin.sysconfig.service.WechatMsgDefaultReplyService;
import com.solution.admin.sysconfig.service.WechatMsgEventReplyService;
import com.solution.admin.sysconfig.service.WechatMsgKeywordReplyService;
import com.solution.common.config.PublicConfig;
import com.solution.common.utils.string.StringUtil;
import com.solution.wx.core.constants.WechatConstants.KEYWORD_MATCH_RULE;
import com.solution.wx.core.constants.WechatConstants.MsgTypeValueEnum;
import com.solution.wx.core.constants.WechatConstants.RECEIVE_EVENT_TYPE;
import com.solution.wx.core.entity.respmsg.ArticleEntity;
import com.solution.wx.core.entity.respmsg.ImageEntity;
import com.solution.wx.core.entity.respmsg.RespImageMessageEntity;
import com.solution.wx.core.entity.respmsg.RespNewsMessageEntity;
import com.solution.wx.core.entity.respmsg.RespTextMessageEntity;
import com.solution.wx.core.service.WechatService;
import com.solution.wx.core.util.MessageUtil;

@Service
public class WechatServiceImpl implements WechatService {
	
	private Logger logger = LoggerFactory.getLogger(WechatServiceImpl.class);
	
	@Autowired
	private WechatMsgKeywordReplyService wechatMsgKeywordReplyService;
	@Autowired
	private WechatMsgConfigService wechatMsgConfigService;
	@Autowired
	private WechatArticleService wechatArticleService;
	@Autowired
	private WechatMsgDefaultReplyService wechatMsgDefaultReplyService;
	@Autowired
	private WechatMsgEventReplyService wechatMsgEventReplyService;
	
	@Autowired
	private KeyMapService keyMapService;

	/**
	 * 微信请求服务器核心方法
	 * 
	 * 假如服务器无法保证在五秒内处理并回复，必须做出下述回复，这样微信服务器才不会对此作任何处理，
	 * 并且不会发起重试（这种情况下，可以使用客服消息接口进行异步回复），否则，将出现严重的错误提示。详见下面说明：
	 * 		1、直接回复success（推荐方式） 
	 * 		2、直接回复空串（指字节长度为0的空字符串，而不是XML结构体中content字段的内容为空）
	 * 一旦遇到以下情况，微信都会在公众号会话中，向用户下发系统提示“该公众号暂时无法提供服务，请稍后再试”：
	 * 		1、开发者在5秒内未回复任何内容
	 * 		2、开发者回复了异常数据，比如JSON数据等
	 * @param request
	 * @return
	 * @author: solin
	 * @date: 2017年12月7日 上午11:39:56
	 */
	public String pushManage(HttpServletRequest request) {
		// xml格式的消息数据
		String respXml = null;
		// 默认返回的文本消息内容
		String respContent = "未知的消息类型";
		try {
			// 调用parseXml方法解析请求消息
			Map requestMap = MessageUtil.parseXml(request);
			System.out.println("消息内容："+JSONObject.toJSONString(requestMap));
			// 发送方帐号
			String fromUserName = (String) requestMap.get("FromUserName");
			// 开发者微信号
			String toUserName = (String) requestMap.get("ToUserName");
			// 消息类型
			String msgType = (String) requestMap.get("MsgType");
			
			// 文本消息
			if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
				//respContent = "您发送的是文本消息！";
				respXml = getMessageByKeyword(requestMap);
			}
			// 图片消息
			else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
				//respContent = "您发送的是图片消息！";
			}
			// 语音消息
			else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
				//respContent = "您发送的是语音消息！";
			}
			// 视频消息
			else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
				//respContent = "您发送的是视频消息！";
			}
			// 地理位置消息
			else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
				//respContent = "您发送的是地理位置消息！";
			}
			// 链接消息
			else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
				//respContent = "您发送的是链接消息！";
			}
			// 事件推送
			else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
				// 事件类型
				String eventType = (String) requestMap.get("Event");
				// 关注
				if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
					//respContent = "谢谢您的关注！";
					respXml = getEventReplayMessage(requestMap);
				}
				// 取消关注
				else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
					//处理取消订阅后用户不会再收到公众账号发送的消息
				}
				// 扫描带参数二维码
				else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
					//处理扫描带参数二维码事件
				}
				// 上报地理位置
				else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {
					//处理上报地理位置事件
				}
				// 自定义菜单
				else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
					//事件KEY值，与自定义菜单接口中KEY值对应
					//处理菜单点击事件
					String key = (String) requestMap.get("EventKey");
					//如果点击的是"促销信息"事件
					if ("promotions".equals(key)) {
						//从字典表中获取配置的消息ＩＤ
						List<KeyMapEntity> keyMapEntities = keyMapService.listKeyMap("promotionClickMsgId");
						if (keyMapEntities.size() > 0) {
							String msgId = keyMapEntities.get(0).getKeyValue();
							//获取消息内筒
							WechatMsgConfigEntity wechatMsgConfigInfo = wechatMsgConfigService.getWechatMsgConfigById(Long.parseLong(msgId));
							respXml = getRespXml(wechatMsgConfigInfo, fromUserName, toUserName);
						}
					}
				}
			} else {
				//默认消息内容
				respXml = respTextMessage(fromUserName, toUserName, respContent);
			}

			return respXml;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}
	
	/**
	 * 获取返回的消息内容
	 * @param wechatMsgConfigInfo 消息配置信息对象
	 * @param fromUserName 发送者
	 * @param toUserName 接收者
	 * @return
	 * @throws UnsupportedEncodingException
	 * @author: solin
	 * @date: 2018年3月10日 下午11:05:53
	 */
	private String getRespXml(WechatMsgConfigEntity wechatMsgConfigInfo, 
			String fromUserName, String toUserName) throws UnsupportedEncodingException {
		String respXml = "";
		
		//消息类型
		String myMsgType = wechatMsgConfigInfo.getMsgType();
		if (MsgTypeValueEnum.TEXT.equals(myMsgType)) { //文本
			String textMessage = wechatMsgConfigInfo.getTextMessage();
			if (StringUtil.isNotEmpty(textMessage)) {
				respXml = respTextMessage(fromUserName, toUserName, textMessage);
			}
		} else if (MsgTypeValueEnum.IMAGE.equals(myMsgType)){//图片
			String mediaId = wechatMsgConfigInfo.getImageMediaId();
			if (StringUtil.isNotEmpty(mediaId)) {
				respXml = respImageMessage(fromUserName, toUserName, mediaId);
			}
		} else if (MsgTypeValueEnum.ARTICLE.equals(myMsgType)){//图文
			Map<String, Object> paramArticle = new HashMap<String, Object>();
			paramArticle.put("msgId", wechatMsgConfigInfo.getId());
			List<WechatArticleEntity> wechatArticles = wechatArticleService.listWechatArticle(paramArticle); //从数据库中获取
			
			List<ArticleEntity> articleList = new ArrayList<ArticleEntity>();
			int articleIndex = 0;
			for (WechatArticleEntity wechatArticle : wechatArticles) {
				ArticleEntity article = new ArticleEntity();
				article.setTitle(wechatArticle.getTitle());
				article.setPicUrl(PublicConfig.IMG_ROOT_URL + wechatArticle.getThumbImageUrl());
				article.setDescription(wechatArticle.getDigest());
				if (1 == wechatArticle.getLinkType()) {
					article.setUrl(PublicConfig.ADMIN_ROOT_URL + "/wechatMsgConfig/toArticleViewPage?msgId=" 
							+ wechatMsgConfigInfo.getId() + "&index=" + articleIndex);
				} else {								
					article.setUrl(PublicConfig.WX_ROOT_URL + "/wx/my/toBindAccountPage?goToUrl="
							+ URLEncoder.encode(wechatArticle.getLinkUrl(), "UTF-8"));
				}
				articleList.add(article);
				
				articleIndex++;
			}
			
			if (articleList.size() > 0) {
				respXml = respArticleMessage(fromUserName, toUserName, articleList);
			}
		}
		return respXml;
	}
	
	/**
	 * 获取回复的关键字信息
	 * @param content
	 * @return
	 * @author: solin
	 * @date: 2017年12月7日 下午7:45:27
	 */
	private String getMessageByKeyword(Map requestMap) {
		String respXml = "";
		
		try {
			// 发送方帐号
			String fromUserName = (String) requestMap.get("FromUserName");
			// 开发者微信号
			String toUserName = (String) requestMap.get("ToUserName");
			// 消息类型
			String msgType = (String) requestMap.get("MsgType");
			// 消息内容
			String content = (String) requestMap.get("Content");
			
			//如果用户发送的是文本消息
			if (MessageUtil.RESP_MESSAGE_TYPE_TEXT.equals(msgType)) {
				Map<String, Object> param = new HashMap<String, Object>();
				param.put("keyword", content);
				List<WechatMsgKeywordReplyEntity> keywordList = wechatMsgKeywordReplyService.listWechatMsgKeywordReply(param);
				if (keywordList != null && keywordList.size() > 0) {
					WechatMsgKeywordReplyEntity keywordInfo = keywordList.get(0); //如果有多条，则取第一条记录。
					//匹配规则 1 完全匹配  2 包含匹配
					String matchRule = keywordInfo.getMatchRule();
					//关键字
					String keyword = keywordInfo.getKeyword();
					//获取消息内筒
					WechatMsgConfigEntity wechatMsgConfigInfo = wechatMsgConfigService.getWechatMsgConfigById(keywordInfo.getMsgId());
					
					if (KEYWORD_MATCH_RULE.PERFECT.equals(matchRule)) { //如果匹配规则是完全匹配
						if (content.equals(keyword)) {
							respXml = getRespXml(wechatMsgConfigInfo, fromUserName, toUserName);
						}
					} else {  //如果匹配规则是模糊匹配
						respXml = getRespXml(wechatMsgConfigInfo, fromUserName, toUserName);
					}
				}
			}
			
			//如果用户发送的消息没有配到关键字词，则使用默认回复
			if (StringUtil.isEmpty(respXml)) {
				//判断系统是否有默认回复配置
				Map<String, Object> param = new HashMap<String, Object>();
				List<WechatMsgDefaultReplyEntity> defaultMsgs = wechatMsgDefaultReplyService.listWechatMsgDefaultReply(param);
				if (null != defaultMsgs && defaultMsgs.size() > 0) {
					//获取消息内筒
					WechatMsgConfigEntity wechatMsgConfigInfo = wechatMsgConfigService.getWechatMsgConfigById(defaultMsgs.get(0).getMsgId());
					respXml = getRespXml(wechatMsgConfigInfo, fromUserName, toUserName);
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return respXml;
	}
	
	/**
	 * 接收事件推送消息
	 * @param requestMap
	 * @return
	 * @author: solin
	 * @date: 2018年2月7日 下午5:35:33
	 */
	private String getEventReplayMessage(Map requestMap) {
		String respXml = "";
		
		try {
			// 发送方帐号
			String fromUserName = (String) requestMap.get("FromUserName");
			// 开发者微信号
			String toUserName = (String) requestMap.get("ToUserName");
			
			Map<String, Object> param = new HashMap<String, Object>();
			param.put("eventType", RECEIVE_EVENT_TYPE.SUBSCRIBE);
			List<WechatMsgEventReplyEntity> eventMsgs = wechatMsgEventReplyService.listWechatMsgEventReply(param);
			if (null != eventMsgs && eventMsgs.size() > 0) {
				//获取消息内筒
				WechatMsgConfigEntity wechatMsgConfigInfo = wechatMsgConfigService.getWechatMsgConfigById(eventMsgs.get(0).getMsgId());
				respXml = getRespXml(wechatMsgConfigInfo, fromUserName, toUserName);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return respXml;
	}
	
	/**
	 * 回复文字消息
	 * @param fromUserName
	 * @param toUserName
	 * @param respContent
	 * @return
	 * @author: solin
	 * @date: 2017年12月7日 下午11:08:29
	 */
	private String respTextMessage(String fromUserName, String toUserName, String respContent) {
		// 回复文本消息
		RespTextMessageEntity textMessage = new RespTextMessageEntity();
		textMessage.setToUserName(fromUserName);
		textMessage.setFromUserName(toUserName);
		textMessage.setCreateTime(new Date().getTime());
		textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
		// 设置文本消息的内容
		textMessage.setContent(respContent);
		// 将文本消息对象转换成xml
		return MessageUtil.textMessageToXml(textMessage);
	}
	
	/**
	 * 回复图片消息
	 * @param fromUserName
	 * @param toUserName
	 * @param mediaId
	 * @return
	 * @author: solin
	 * @date: 2018年2月7日 下午5:22:12
	 */
	private String respImageMessage(String fromUserName, String toUserName, String mediaId) {
		// 回复文本消息
		RespImageMessageEntity imageMessage = new RespImageMessageEntity();
		imageMessage.setToUserName(fromUserName);
		imageMessage.setFromUserName(toUserName);
		imageMessage.setCreateTime(new Date().getTime());
		imageMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_IMAGE);
		ImageEntity image = new ImageEntity();
		// 设置图片消息的内容
		image.setMediaId(mediaId);
		imageMessage.setImage(image);
		// 将文本消息对象转换成xml
		return MessageUtil.imageMessageToXml(imageMessage);
	}
	
	/**
	 * 回复图文信息
	 * @param fromUserName
	 * @param toUserName
	 * @param articles
	 * @return
	 * @author: solin
	 * @date: 2017年12月7日 下午11:21:42
	 */
	private String respArticleMessage(String fromUserName, String toUserName, List<ArticleEntity> articles) {
		RespNewsMessageEntity newsMessage = new RespNewsMessageEntity();
		newsMessage.setToUserName(fromUserName);
		newsMessage.setFromUserName(toUserName);
		newsMessage.setCreateTime(new Date().getTime());
		newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS);
		//图文消息个数，限制为8条以内
		newsMessage.setArticleCount(articles.size());
		//多条图文消息信息，默认第一个item为大图,注意，如果图文数超过8，则将会无响应
		newsMessage.setArticles(articles);
		
		return MessageUtil.articlesMessageToXml(newsMessage);
	}
}
